package cn.xopencode.oss.service.permission;

import cn.xopencode.common.framework.util.CollectionUtils;
import cn.xopencode.common.framework.exception.util.ServiceExceptionUtil;
import cn.xopencode.common.framework.vo.PageResult;
import cn.xopencode.oss.convert.permission.PositionConvert;
import cn.xopencode.oss.dal.mysql.dataobject.permission.AdminPositionDO;
import cn.xopencode.oss.dal.mysql.dataobject.permission.PositionDO;
import cn.xopencode.oss.dal.mysql.mapper.permission.AdminPositionMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.PositionMapper;
import cn.xopencode.oss.dal.mysql.mapper.permission.PositionResourceMapper;
import cn.xopencode.oss.enums.permission.PositionCodeEnum;
import cn.xopencode.oss.enums.permission.PositionTypeEnum;
import cn.xopencode.oss.service.permission.bo.PositionBO;
import cn.xopencode.oss.service.permission.bo.PositionCreateBO;
import cn.xopencode.oss.service.permission.bo.PositionPageBO;
import cn.xopencode.oss.service.permission.bo.PositionUpdateBO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import static cn.xopencode.oss.enums.SystemErrorCodeConstants.*;

/**
* 职务 Service
*/
@Service
@Validated
public class PositionService {

    @Autowired
    private PositionMapper positionMapper;

    @Autowired
    private PositionResourceMapper positionResourceMapper;

    /**
    * 创建职务
    *
    * @param createBO 创建职务 BO
    * @return 职务
    */
    public PositionBO createPosition(@Valid PositionCreateBO createBO) {
        // 校验职务
        checkDuplicatePosition(createBO.getName(), createBO.getCode(), null);
        // 插入到数据库
        PositionDO positionDO = PositionConvert.INSTANCE.convert(createBO);
        positionDO.setPositionType(PositionTypeEnum.CUSTOM.getType());
        positionMapper.insert(positionDO);
        // 返回
        return PositionConvert.INSTANCE.convert(positionDO);
    }

    /**
    * 更新职务
    *
    * @param updateBO 更新职务 BO
    */
    public void updatePosition(@Valid PositionUpdateBO updateBO) {
        // 校验更新的职务是否存在
        PositionDO positionDO = positionMapper.selectById(updateBO.getId());
        if (positionMapper.selectById(updateBO.getId()) == null) {
            throw ServiceExceptionUtil.exception(Position_NOT_EXISTS);
        }
        // 内置职务，不允许修改
        if (PositionTypeEnum.SYSTEM.getType().equals(positionDO.getPositionType())) {
            throw ServiceExceptionUtil.exception(Position_CAN_NOT_UPDATE_SYSTEM_TYPE_Position);
        }
        // 校验职务的唯一字段是否重复
        checkDuplicatePosition(updateBO.getName(), updateBO.getCode(), updateBO.getId());
        // 更新到数据库
        PositionDO updateObject = PositionConvert.INSTANCE.convert(updateBO);
        positionMapper.updateById(updateObject);
    }

    /**
    * 删除职务
    *
    * @param positionId 职务编号
    */
    public void deletePosition(String positionId) {
        // 校验删除的职务是否存在
        PositionDO positionDO = positionMapper.selectById(positionId);
        if (positionMapper.selectById(positionId) == null) {
            throw ServiceExceptionUtil.exception(Position_NOT_EXISTS);
        }
        // 内置职务，不允许删除
        if (PositionTypeEnum.SYSTEM.getType().equals(positionDO.getPositionType())) {
            throw ServiceExceptionUtil.exception(Position_CAN_NOT_DELETE_SYSTEM_TYPE_Position);
        }
        //查询是否还有担任此职务的员工，如果有则不能删除

        // 标记删除
        positionMapper.deleteById(positionId);
        // 标记删除 PositionResource
        positionResourceMapper.deleteByPositionId(positionId);
    }

    /**
    * 获得职务
    *
    * @param PositionId 职务编号
    * @return 职务
    */
    public PositionBO getPosition(String PositionId) {
        PositionDO positionDO = positionMapper.selectById(PositionId);
        return PositionConvert.INSTANCE.convert(positionDO);
    }

    /**
     * 获得所有职务
     *
     * @return 职务列表
     */
    public List<PositionBO> listAllPosition() {
        List<PositionDO> positionDOS = positionMapper.selectList(null);
        return PositionConvert.INSTANCE.convertList(positionDOS);
    }

    /**
    * 获得职务列表
    *
    * @param PositionIds 职务编号列表
    * @return 职务列表
    */
    public List<PositionBO> listPosition(Collection<String> PositionIds) {
        List<PositionDO> positionDOS = positionMapper.selectBatchIds(PositionIds);
        return PositionConvert.INSTANCE.convertList(positionDOS);
    }

    /**
     * 获得职务分页
     *
     * @param pageBO 职务分页查询
     * @return 职务分页结果
     */
    public PageResult<PositionBO> pagePosition(PositionPageBO pageBO) {
        IPage<PositionDO> PositionDOPage = positionMapper.selectPage(pageBO);
        return PositionConvert.INSTANCE.convertPage(PositionDOPage);
    }

    /**
     * 校验职务的唯一字段是否重复
     *
     * 1. 是否存在相同名字的职务
     * 2. 是否存在相同编码的职务
     *
     * @param name 职务名字
     * @param code 职务额编码
     * @param id 职务编号
     */
    private void checkDuplicatePosition(String name, String code, Integer id) {
        // 1. 该 name 名字被其它职务所使用
        PositionDO Position = positionMapper.selectByName(name);
        if (Position != null && !Position.getId().equals(id)) {
            throw ServiceExceptionUtil.exception(Position_NAME_DUPLICATE, name);
        }
        // 2. 是否存在相同编码的职务
        if (!StringUtils.hasText(code)) {
            return;
        }
        // 该 code 编码被其它职务所使用
        Position = positionMapper.selectByCode(code);
        if (Position != null && !Position.getId().equals(id)) {
            throw ServiceExceptionUtil.exception(Position_CODE_DUPLICATE, name);
        }
    }



    /**
     * 判断职务是否有超级管理员
     *
     * @param positionIds 职务编号列表
     * @return 是否有超级管理员
     */
    public boolean hasSuperAdmin(Collection<String> positionIds) {
        List<PositionDO> positionDOS = positionMapper.selectBatchIds(positionIds);
        for (PositionDO positionDO : positionDOS) {
            if (PositionCodeEnum.SUPER_ADMIN.getCode().equals(positionDO.getCode())) {
                return true;
            }
        }
        return false;
    }

}
